package com.heima.wemedia.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.heima.client.article.IArticleClient;
import com.heima.comment.pojos.ApComment;
import com.heima.comment.pojos.ApCommentLike;
import com.heima.comment.pojos.ApCommentRepay;
import com.heima.comment.pojos.ApCommentReplyLike;
import com.heima.comment.vo.FindCommentsVo;
import com.heima.comment.vo.ListCommentDetailVo;
import com.heima.common.exception.CustomException;
import com.heima.common.redis.CacheService;
import com.heima.model.common.comment.dtos.CommentDetailPageDto;
import com.heima.model.common.comment.dtos.CommentLikeDto;
import com.heima.model.common.comment.dtos.CommentManagePageDto;
import com.heima.model.common.comment.dtos.CommentRepayDto;
import com.heima.model.common.dtos.ArticleDto;
import com.heima.model.common.dtos.CommentUpdateStatusDto;
import com.heima.model.common.dtos.PageResponseResult;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.common.pojos.article.ApArticle;
import com.heima.model.common.pojos.wemedia.WmSensitive;
import com.heima.utils.common.SensitiveWordUtil;
import com.heima.utils.thread.WmThreadLocalUtil;
import com.heima.wemedia.mapper.WmSensitiveMapper;
import com.heima.wemedia.service.BaiduScanService;
import com.heima.wemedia.service.CommentManageService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;


/**
 * Description:
 * Author: Wzh
 * Date: 2024/8/1
 */
@Service
@Slf4j
public class CommentManageImpl implements CommentManageService {
    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private IArticleClient articleClient;
    @Autowired
    private BaiduScanService baiduScanService;
    @Autowired
    private CacheService cacheService;
    @Autowired
    private WmSensitiveMapper wmSensitiveMapper;

    /**
     * 评论管理查询
     *
     * @param commentDto
     * @return
     */
    @Override
    public ResponseResult findComments(CommentManagePageDto commentDto) {
        if (commentDto == null) {
            throw new CustomException(AppHttpCodeEnum.PARAM_INVALID);
        }
        commentDto.getFromIndex();
        // 假设 commentDto 已经初始化并且 endDate 是 Date 类型
        Date endDate = commentDto.getEndDate();
        // 获取今天的日期
        LocalDate today = LocalDate.now();
        // 设置时间为一天中的最大值
        LocalTime maxTime = LocalTime.MAX;
        // 组合日期和时间
        LocalDateTime endOfDay = LocalDateTime.of(today, maxTime);
        // 转换为 Date 类型
        Date endOfDayDate = Date.from(endOfDay.atZone(ZoneId.systemDefault()).toInstant());
        // 设置到 commentDto
        commentDto.setEndDate(endOfDayDate);

        // 调用文章微服务查询所有符合条件文章
        //此处是通过wemedia客户端登录进来 需要从wemdia拦截器中使用的thread中获取,远程调用之后获取不了
        commentDto.setAuthorId(WmThreadLocalUtil.get());
        PageResponseResult result = articleClient.findList(commentDto);
        if (result.getCode() == 200) {
            String jsonString = JSON.toJSONString(result.getData());
            List<ApArticle> articles = JSONArray.parseArray(jsonString, ApArticle.class);
            List<FindCommentsVo> commentsVoList = new ArrayList<>();
            for (ApArticle apArticle : articles) {
                FindCommentsVo commentsVo = new FindCommentsVo();
                BeanUtils.copyProperties(apArticle, commentsVo);
                commentsVo.setTitle(apArticle.getTitle());
                commentsVo.setComments(apArticle.getComment());
                commentsVo.setIsComment(apArticle.getIsComment());
                commentsVoList.add(commentsVo);
            }
            result.setData(commentsVoList);
        }
        return result;
//        //1.在mongoDB中查询符合条件的数据
//        Query query = Query.query(
//                        Criteria.where("createdTime")
//                                .gte(commentDto.getBeginDate()) // 开始日期
//                                .lte(commentDto.getEndDate())   // 结束日期
//                )
//                .with(Sort.by(Sort.Order.desc("createdTime"))) // 按照 createdTime 降序排序
//                .with(PageRequest.of(commentDto.getPage() - 1, commentDto.getSize())); // 分页
//
//        // 创建 Pageable 对象
//        Pageable pageable = PageRequest.of(commentDto.getPage() - 1, commentDto.getSize());
//
//        // 执行分页查询
//        List<ApComment> comments = mongoTemplate.find(query, ApComment.class, "ap_comment");
//
//        List<FindCommentsVo> commentsVoList = new ArrayList<>();
//        for (ApComment comment : comments) {
//            FindCommentsVo commentsVo = new FindCommentsVo();
//            BeanUtils.copyProperties(comment, commentsVo);
//            //开启远程调用文章微服务article查询文章信息
//            ResponseResult result = articleClient.getArticleInfo(commentsVo.getEntryId());
//            if (result.getCode() == 200) {
//                ApArticle apArticle = JSONObject.parseObject(JSON.toJSONString(result.getData()), ApArticle.class);
//                commentsVo.setTitle(apArticle.getTitle());
//                commentsVo.setComments(apArticle.getComment());
//                commentsVo.setIsComment(apArticle.getIsComment());
//            }
//            commentsVoList.add(commentsVo);
//        }
//        // 计算满足条件的记录总数
//        long totalRecords = mongoTemplate.count(query, ApComment.class);
//
//        // 创建 Page 对象
//        Page<ApComment> pageResult = new PageImpl<>(comments, pageable, totalRecords);
//
//        // 提取分页信息
//        int current = pageResult.getNumber(); // 当前页索引
//        int size = pageResult.getSize();           // 每页大小
//        long total = pageResult.getTotalElements(); // 总记录数
//        PageResponseResult result = new PageResponseResult(current, size, (int) total);
//        result.setData(commentsVoList);
//        return result;
    }

    /**
     * 打开/关闭文章评论
     *
     * @param statusDto
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult updateStatus(CommentUpdateStatusDto statusDto) {
        if (statusDto == null) {
            throw new CustomException(AppHttpCodeEnum.PARAM_INVALID);
        }
        //远程调用文章微服务更改article_config中的评论状态
        // 去除字符串首尾的空白字符
        String articleId = statusDto.getArticleId().trim();
        Query query = Query.query(Criteria.where("entryId").is(Long.parseLong(articleId)));
        List<ApComment> comments = mongoTemplate.find(query, ApComment.class);
        if (statusDto.getOperation() == 0) {
            //如果是关闭评论的话 还需要将相关的文章评论/回复/喜欢全部删除,及在微服务中将comment数量修改为0
            if (!comments.isEmpty()) {
                for (ApComment comment : comments) {
                    mongoTemplate.remove(Query.query(Criteria.where("entryId").is(comment.getEntryId())), ApComment.class);
                    mongoTemplate.remove(Query.query(Criteria.where("commentId").is(comment.getId())), ApCommentLike.class);
                    //先查询到回复的数量然后删除
                    List<ApCommentRepay> commentRepays = mongoTemplate.find(Query.query(Criteria.where("commentId").is(comment.getId())), ApCommentRepay.class);
                    mongoTemplate.remove(Query.query(Criteria.where("commentId").is(comment.getId())), ApCommentRepay.class);
                    commentRepays.forEach(commentRepay -> mongoTemplate.remove(Query
                            .query(Criteria.where("commentRepayId").is(commentRepay.getId())), ApCommentReplyLike.class));
                }
            }
        }
        ResponseResult result = articleClient.updateArticleCommentStatus(statusDto);
        if (result.getCode() == 200) {
            return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
        }
        return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR);
    }

    /**
     * 查看文章评论详情
     *
     * @param detailPageDto
     * @return
     */
    @Override
    public ResponseResult listCommentDetail(CommentDetailPageDto detailPageDto) {
        if (detailPageDto == null || detailPageDto.getArticleId() == null) {
            throw new CustomException(AppHttpCodeEnum.PARAM_INVALID);
        }
        detailPageDto.getFromIndex();

        //封装数据的VO
        ArrayList<ListCommentDetailVo> list = new ArrayList<>();

        //1.根据文章ID查询对应的评论
        String articleId = detailPageDto.getArticleId().trim();
        Query query = Query.query(Criteria.where("entryId").is(Long.parseLong(articleId)))
                .with(Sort.by(Sort.Order.desc("createdTime"))) // 按照 createdTime 降序排序
                .with(PageRequest.of(detailPageDto.getPage() - 1, detailPageDto.getSize())); // 分页
        List<ApComment> comments = mongoTemplate.find(query, ApComment.class);
        //2.根据评论查询对应的回复
        for (ApComment comment : comments) {
            Query query2 = Query.query(Criteria.where("commentId").is(comment.getId()))
                    .with(Sort.by(Sort.Order.desc("createdTime"))) // 按照 createdTime 降序排序
                    .with(PageRequest.of(detailPageDto.getPage() - 1, detailPageDto.getSize())); // 分页
            List<ApCommentRepay> commentRepays = mongoTemplate.find(query2, ApCommentRepay.class);
            ListCommentDetailVo vo = new ListCommentDetailVo();
            vo.setApComments(comment);
            vo.setApCommentRepays(commentRepays);
            list.add(vo);
        }
        //3.封装数据返回
        return ResponseResult.okResult(list);
    }

    /**
     * 作者回复评论
     *
     * @param repayDto
     * @return
     */
    @Override
    public ResponseResult repayComment(CommentRepayDto repayDto) {
        if (repayDto == null || repayDto.getCommentId() == null
                || StringUtils.isEmpty(repayDto.getContent()))
            throw new CustomException(AppHttpCodeEnum.PARAM_INVALID);

        //评论文本审核
        //1.先内审：走自定义敏感词库过滤
        //1.1加载系统敏感词数据
        //缓存优化：先查缓存，缓存有：直接用，缓存没有：再查数据库，并将查到的数据添加到缓存
        String sensitivesJSON = cacheService.get("sensitives");
        List<String> sensitiveList = JSONArray.parseArray(sensitivesJSON, String.class);
        for (String sensitive : sensitiveList) {
            //如果缓存包含敏感词
            if (sensitive.equals(repayDto.getContent())) {
                throw new CustomException(AppHttpCodeEnum.VIOLATING_TEXT);
            } else {
                //如果缓存里没有，查询数据库
                List<WmSensitive> wmSensitives = wmSensitiveMapper.selectList(null);
                sensitiveList = wmSensitives.stream().map(WmSensitive::getSensitives).collect(Collectors.toList());
                //添加到缓存
                cacheService.set("sensitives", JSON.toJSONString(sensitiveList));
            }
        }

        //1.2初始化DFA算法字典
        SensitiveWordUtil.initMap(sensitiveList);
        //1.3调用DFA算法进行指定文本的敏感词过滤
        Map<String, Integer> resMap = SensitiveWordUtil.matchWords(repayDto.getContent());
        if (resMap != null && resMap.size() > 0) {
            throw new CustomException(AppHttpCodeEnum.VIOLATING_TEXT);
        }
        //2. 再外审：走第三方文本审核接口：百度云API
        Integer result = baiduScanService.scanText(repayDto.getContent());
        if (result != 1)
            throw new CustomException(AppHttpCodeEnum.VIOLATING_TEXT);

        //填充数据
        ApCommentRepay apCommentRepay = new ApCommentRepay();
        apCommentRepay.setCommentId(repayDto.getCommentId());
        apCommentRepay.setContent(repayDto.getContent());
        apCommentRepay.setCreatedTime(new Date());
        apCommentRepay.setUpdatedTime(new Date());

        //填充作者id和name
        ApComment apComment = mongoTemplate.findOne(Query.query(Criteria.where("id").is(repayDto.getCommentId())), ApComment.class);
        apCommentRepay.setAuthorId(apComment.getAuthorId());
        apCommentRepay.setAuthorName(apComment.getAuthorName());
        //保存到评论回复表中
        mongoTemplate.save(apCommentRepay);

        //回复评论成功，评论表里回复数加1
        apComment.setReply(apComment.getReply() + 1);
        mongoTemplate.save(apComment);

        //回复评论成功，文章表里评论数加1
        ResponseResult articleInfo = articleClient.getArticleInfo(apComment.getEntryId());
        if (articleInfo.getCode() == 200) {
            String jsonString = JSON.toJSONString(articleInfo.getData());
            ApArticle apArticle = JSONObject.parseObject(jsonString, ApArticle.class);
            log.info("article:{}", apArticle);
            ArticleDto articleDto = new ArticleDto();
            BeanUtils.copyProperties(apArticle, articleDto);
            articleDto.setComment(apArticle.getComment() + 1);
            articleClient.syncArticle(articleDto);
        }

        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    /**
     * 评论点赞
     *
     * @param likeDto
     * @return
     */
    @Override
    public ResponseResult likeComment(CommentLikeDto likeDto) {
        if (likeDto == null || StringUtils.isEmpty(likeDto.getCommentId())
                || likeDto.getOperation() < 0 || likeDto.getOperation() > 1)
            throw new CustomException(AppHttpCodeEnum.PARAM_INVALID);
        //operation=0,点赞数+1
        //operation=1，点赞数-1
        ApCommentLike apCommentLike = new ApCommentLike();
        ApComment apComment = mongoTemplate.findOne(Query.query(Criteria.where("id").is(likeDto.getCommentId())), ApComment.class);
        if (apComment != null && likeDto.getOperation() == 0) {
            //如果点赞该评论的作者id已存在，不允许重复点赞
            ApCommentLike commentLike = mongoTemplate.findOne(Query.query(Criteria.where("authorId").is(apComment.getAuthorId())
                    .and("commentId").is(likeDto.getCommentId())), ApCommentLike.class);
            if (commentLike != null) {
                return ResponseResult.errorResult(AppHttpCodeEnum.DATA_EXIST);
            }

            apComment.setLikes(apComment.getLikes() + 1);
            //保存新增点赞数到评论表
            mongoTemplate.save(apComment);
            //填充点赞评论表的数据
            apCommentLike.setAuthorId(apComment.getAuthorId());
            apCommentLike.setCommentId(likeDto.getCommentId());
            mongoTemplate.save(apCommentLike);
        } else if (apComment != null && likeDto.getOperation() == 1) {
            //取消点赞，评论表里点赞数-1
            if (apComment.getLikes() - 1 < 0) {
                apComment.setLikes(0);
            }
            apComment.setLikes(apComment.getLikes() - 1);
            mongoTemplate.save(apComment);
            //删除点赞评论表的数据
            mongoTemplate.remove(Query.query(Criteria.where("commentId").is(likeDto.getCommentId())), ApCommentLike.class);

        }

        //返回点赞数量
        Map<String, Object> result = new HashMap<>();
        result.put("likes", apComment.getLikes());
        return ResponseResult.okResult(result);

    }

}

